package com.derschmale.wick3d.shaders
{
	import com.derschmale.wick3d.core.data.RenderPipelineData;
	import com.derschmale.wick3d.core.geometry.Triangle3D;
	import com.derschmale.wick3d.core.math.Vector3D;
	import com.derschmale.wick3d.core.utils.Colour;
	import com.derschmale.wick3d.lights.AbstractLight;
	import com.derschmale.wick3d.materials.TextureMaterial;
	import com.derschmale.wick3d.view.Viewport;
	
	import flash.display.BitmapData;
	import flash.display.BlendMode;
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.geom.Rectangle;

	public class FlatShader extends AbstractShader implements IShader
	{
		public static const MODE_MATTE : String = "multiply";
		public static const MODE_METALLIC : String = "overlay";
		
		private static var _point : Vector3D = new Vector3D();
		
		private var _shade : Sprite = new Sprite();
		
		public var mode : String = MODE_MATTE;
		
		public function FlatShader()
		{
			super();
		}
		
		override public function generateShadedBitmapData(triangle:Triangle3D, pipelineData:RenderPipelineData):BitmapData
		{
			var orig : BitmapData = TextureMaterial(triangle.material).bitmapData;
			var w : Number = orig.width, h : Number = orig.height;
			var bmp : BitmapData = pipelineData.shaderData.getTriangleBitmapData(triangle);
			var graphics : Graphics = _shade.graphics;
			var colour : Number = calculateColour(triangle, pipelineData.lights);
			var rect : Rectangle = pipelineData.shaderData.getRectangle(triangle);
			graphics.clear();
			graphics.beginFill(colour);
			graphics.drawRect(0, 0, rect.width, rect.height);
			graphics.endFill();
			
			bmp.draw(_shade, null, null, mode);
			
			return bmp;
		}
		
		override public function drawTriangleToLayer(triangle:Triangle3D, viewport:Viewport, pipelineData:RenderPipelineData):void
		{
			var colour : int = calculateColour(triangle, pipelineData.lights);
			var graphics : Graphics = viewport.getShaderLayer(triangle.parent, mode).graphics;
			
			graphics.beginFill(colour);
			graphics.moveTo(triangle.v1.coords2D.x, triangle.v1.coords2D.y);
			graphics.lineTo(triangle.v2.coords2D.x, triangle.v2.coords2D.y);
			graphics.lineTo(triangle.v3.coords2D.x, triangle.v3.coords2D.y);
			graphics.endFill();
		}
		
		override public function get requiresVertexInfo():Boolean
		{
			return false;
		}
		
		private function calculateColour(triangle : Triangle3D, lights : Array) : int
		{
			var totalColour : Colour = new Colour(0, 0, 0);
			var colour : Colour;
			var i : int = lights.length;
			var light : AbstractLight;
			var dot : Number;
			var ray : Vector3D;
			
			_point.x = (triangle.v1.x+triangle.v2.x+triangle.v3.x)*0.333333;
			_point.y = (triangle.v1.y+triangle.v2.y+triangle.v3.y)*0.333333;
			_point.z = (triangle.v1.z+triangle.v2.z+triangle.v3.z)*0.333333;
			
			while (light = lights[--i] as AbstractLight) {
				ray = _point.subtract(light.viewPosition);
				ray.normalize();
				colour = light.calculateColourImpact(_point);
				dot = Math.max(triangle.normal.dotProduct(ray), 0);
				
				totalColour.r += colour.r*dot; 
				totalColour.g += colour.g*dot;
				totalColour.b += colour.b*dot;
				
			}
			
			totalColour.r *= _diffuseR;
			totalColour.g *= _diffuseG;
			totalColour.b *= _diffuseB;
			
			totalColour.clip();
			return totalColour.toHex();
		}
		
	}
}